"use client";

import React from "react";
import { type ColumnDef } from "@tanstack/react-table";
import {
  type VulnerabilityWithSource,
  type SourceAttribution,
} from "~/types/scanTypes";
import { cn } from "~/components/lib/utils";
import { ExternalLink, Eye, Clock, Shield, Users, Filter } from "lucide-react";

// Enhanced vulnerability table data with source attribution
export interface VulnTableDataWithSources {
  cve: string;
  severity: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFORMATIONAL";
  description: string;
  riskScore: number;
  references: string[];
  affectedHosts: string[];
  sources: SourceAttribution[];
  port?: number;
  service_info?: string;
  first_detected?: string;
  last_confirmed?: string;
  confidence_score?: number;
  selected?: boolean;
}

// Utility function to render a severity badge
const SeverityBadge = ({ severity }: { severity: string }) => {
  const colorMap: Record<string, { bg: string; text: string }> = {
    CRITICAL: {
      bg: "bg-red-100 dark:bg-red-900/20",
      text: "text-red-800 dark:text-red-300",
    },
    HIGH: {
      bg: "bg-orange-100 dark:bg-orange-900/20",
      text: "text-orange-800 dark:text-orange-300",
    },
    MEDIUM: {
      bg: "bg-yellow-100 dark:bg-yellow-900/20",
      text: "text-yellow-800 dark:text-yellow-300",
    },
    LOW: {
      bg: "bg-green-100 dark:bg-green-900/20",
      text: "text-green-800 dark:text-green-300",
    },
    INFORMATIONAL: {
      bg: "bg-blue-100 dark:bg-blue-900/20",
      text: "text-blue-800 dark:text-blue-300",
    },
  };

  const config = colorMap[severity] || colorMap.INFORMATIONAL;

  return (
    <div className={cn("rounded-full px-2.5 py-0.5 text-center", config.bg)}>
      <span className={cn("text-xs font-medium", config.text)}>
        {severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase()}
      </span>
    </div>
  );
};

// Source badge component
const SourceBadge = ({ source }: { source: string }) => {
  const getSourceColor = (source: string) => {
    switch (source.toLowerCase()) {
      case "nmap":
        return "bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-300";
      case "agent":
        return "bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-300";
      case "rustscan":
        return "bg-orange-100 text-orange-800 dark:bg-orange-900/20 dark:text-orange-300";
      case "manual":
        return "bg-purple-100 text-purple-800 dark:bg-purple-900/20 dark:text-purple-300";
      case "naabu":
        return "bg-cyan-100 text-cyan-800 dark:bg-cyan-900/20 dark:text-cyan-300";
      default:
        return "bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-300";
    }
  };

  return (
    <span
      className={cn(
        "inline-flex items-center rounded-full px-2 py-1 text-xs font-medium",
        getSourceColor(source)
      )}
    >
      {source}
    </span>
  );
};

// Confidence score component
const ConfidenceScore = ({ score }: { score: number }) => {
  const getConfidenceColor = (score: number) => {
    if (score >= 0.9) return "text-green-600 dark:text-green-400";
    if (score >= 0.7) return "text-yellow-600 dark:text-yellow-400";
    return "text-red-600 dark:text-red-400";
  };

  return (
    <div className="flex items-center gap-1">
      <Shield className="h-3 w-3" />
      <span className={cn("text-xs font-medium", getConfidenceColor(score))}>
        {(score * 100).toFixed(0)}%
      </span>
    </div>
  );
};

// Time ago utility
const timeAgo = (dateString: string) => {
  const date = new Date(dateString);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));

  if (diffDays === 0) return "Today";
  if (diffDays === 1) return "1 day ago";
  if (diffDays < 7) return `${diffDays} days ago`;
  if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;
  return `${Math.floor(diffDays / 30)} months ago`;
};

// Enhanced columns with source attribution
export const columnsWithSources: ColumnDef<VulnTableDataWithSources>[] = [
  {
    accessorKey: "severity",
    header: "Severity",
    cell: ({ row }) => {
      const severity = row.getValue("severity") as string;
      return <SeverityBadge severity={severity} />;
    },
    filterFn: (row, id, value) => {
      return value.includes(row.getValue(id));
    },
  },
  {
    accessorKey: "cve",
    header: "CVE ID",
    cell: ({ row }) => (
      <span className="font-mono text-xs font-medium">
        {row.getValue("cve")}
      </span>
    ),
  },
  {
    accessorKey: "sources",
    header: "Sources",
    cell: ({ row }) => {
      const sources = row.getValue("sources") as SourceAttribution[];
      if (!sources || sources.length === 0) {
        return <span className="text-xs text-gray-400">Unknown</span>;
      }

      return (
        <div className="flex flex-wrap gap-1">
          {sources.slice(0, 2).map((source, index) => (
            <SourceBadge key={index} source={source.source} />
          ))}
          {sources.length > 2 && (
            <span className="text-xs text-gray-500">+{sources.length - 2}</span>
          )}
        </div>
      );
    },
    filterFn: (row, id, value) => {
      const sources = row.getValue(id) as SourceAttribution[];
      if (!sources) return false;
      return sources.some((source) => value.includes(source.source));
    },
  },
  {
    accessorKey: "confidence_score",
    header: "Confidence",
    cell: ({ row }) => {
      const sources = row.getValue("sources") as SourceAttribution[];
      if (!sources || sources.length === 0) return null;

      const avgConfidence =
        sources.reduce((sum, s) => sum + s.confidence, 0) / sources.length;
      return <ConfidenceScore score={avgConfidence} />;
    },
    sortingFn: (rowA, rowB, columnId) => {
      const sourcesA = rowA.getValue("sources") as SourceAttribution[];
      const sourcesB = rowB.getValue("sources") as SourceAttribution[];

      const avgA = sourcesA?.length
        ? sourcesA.reduce((sum, s) => sum + s.confidence, 0) / sourcesA.length
        : 0;
      const avgB = sourcesB?.length
        ? sourcesB.reduce((sum, s) => sum + s.confidence, 0) / sourcesB.length
        : 0;

      return avgA - avgB;
    },
  },
  {
    accessorKey: "first_detected",
    header: "First Seen",
    cell: ({ row }) => {
      const sources = row.getValue("sources") as SourceAttribution[];
      if (!sources || sources.length === 0) return null;

      const earliestDate = sources.reduce((earliest, source) => {
        const sourceDate = new Date(source.first_seen);
        return sourceDate < earliest ? sourceDate : earliest;
      }, new Date(sources[0].first_seen));

      return (
        <div className="flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400">
          <Clock className="h-3 w-3" />
          {timeAgo(earliestDate.toISOString())}
        </div>
      );
    },
    sortingFn: (rowA, rowB, columnId) => {
      const sourcesA = rowA.getValue("sources") as SourceAttribution[];
      const sourcesB = rowB.getValue("sources") as SourceAttribution[];

      if (!sourcesA?.length || !sourcesB?.length) return 0;

      const earliestA = sourcesA.reduce((earliest, source) => {
        const sourceDate = new Date(source.first_seen);
        return sourceDate < earliest ? sourceDate : earliest;
      }, new Date(sourcesA[0].first_seen));

      const earliestB = sourcesB.reduce((earliest, source) => {
        const sourceDate = new Date(source.first_seen);
        return sourceDate < earliest ? sourceDate : earliest;
      }, new Date(sourcesB[0].first_seen));

      return earliestA.getTime() - earliestB.getTime();
    },
  },
  {
    accessorKey: "last_confirmed",
    header: "Last Seen",
    cell: ({ row }) => {
      const sources = row.getValue("sources") as SourceAttribution[];
      if (!sources || sources.length === 0) return null;

      const latestDate = sources.reduce((latest, source) => {
        const sourceDate = new Date(source.last_seen);
        return sourceDate > latest ? sourceDate : latest;
      }, new Date(sources[0].last_seen));

      return (
        <div className="flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400">
          <Clock className="h-3 w-3" />
          {timeAgo(latestDate.toISOString())}
        </div>
      );
    },
    sortingFn: (rowA, rowB, columnId) => {
      const sourcesA = rowA.getValue("sources") as SourceAttribution[];
      const sourcesB = rowB.getValue("sources") as SourceAttribution[];

      if (!sourcesA?.length || !sourcesB?.length) return 0;

      const latestA = sourcesA.reduce((latest, source) => {
        const sourceDate = new Date(source.last_seen);
        return sourceDate > latest ? sourceDate : latest;
      }, new Date(sourcesA[0].last_seen));

      const latestB = sourcesB.reduce((latest, source) => {
        const sourceDate = new Date(source.last_seen);
        return sourceDate > latest ? sourceDate : latest;
      }, new Date(sourcesB[0].last_seen));

      return latestA.getTime() - latestB.getTime();
    },
  },
  {
    accessorKey: "riskScore",
    header: "Risk Score",
    cell: ({ row }) => {
      const score = parseFloat(row.getValue("riskScore"));
      let color = "bg-blue-500";
      if (score >= 9.0) color = "bg-red-500";
      else if (score >= 7.0) color = "bg-orange-500";
      else if (score >= 4.0) color = "bg-yellow-500";
      else if (score > 0) color = "bg-green-500";

      return (
        <div className="flex items-center">
          <div className="mr-2 text-xs font-medium">{score.toFixed(1)}</div>
          <div className="h-1.5 w-12 rounded-full bg-gray-200 dark:bg-gray-700">
            <div
              className={`h-1.5 rounded-full ${color}`}
              style={{ width: `${Math.min(score * 10, 100)}%` }}
            ></div>
          </div>
        </div>
      );
    },
  },
  {
    accessorKey: "description",
    header: "Description",
    cell: ({ row }) => {
      const description = row.getValue("description") as string;
      return (
        <div className="max-w-[400px] text-xs text-gray-900 dark:text-gray-100">
          <div className="line-clamp-2">{description}</div>
        </div>
      );
    },
  },
  {
    accessorKey: "affectedHosts",
    header: "Hosts",
    cell: ({ row }) => {
      const hosts = row.getValue("affectedHosts") as string[];
      return (
        <div className="flex items-center gap-1 text-center">
          <Users className="h-3 w-3 text-gray-400" />
          <span className="text-xs font-medium text-gray-900 dark:text-gray-100">
            {hosts.length}
          </span>
        </div>
      );
    },
  },
  {
    id: "actions",
    cell: ({ row }) => {
      const cve = row.getValue("cve") as string;
      return (
        <div className="flex justify-end gap-2">
          <button
            onClick={(e) => {
              e.stopPropagation();
              // The parent will need to implement the view details handler
            }}
            className="rounded p-1 text-gray-400 hover:bg-gray-100 hover:text-violet-600 dark:hover:bg-gray-700 dark:hover:text-violet-400"
            title="View vulnerability details"
          >
            <Eye className="h-4 w-4" />
          </button>
          <a
            href={`https://nvd.nist.gov/vuln/detail/${cve}`}
            target="_blank"
            rel="noopener noreferrer"
            className="rounded p-1 text-gray-400 hover:bg-gray-100 hover:text-blue-600 dark:hover:bg-gray-700 dark:hover:text-blue-400"
            title="View in NVD database"
            onClick={(e) => e.stopPropagation()}
          >
            <ExternalLink className="h-4 w-4" />
          </a>
        </div>
      );
    },
  },
];

// Source filter options for the filter interface
export const sourceFilterOptions = [
  { value: "nmap", label: "Nmap", color: "blue" },
  { value: "agent", label: "Agent", color: "green" },
  { value: "rustscan", label: "RustScan", color: "orange" },
  { value: "manual", label: "Manual", color: "purple" },
  { value: "naabu", label: "Naabu", color: "cyan" },
];

// Confidence filter options
export const confidenceFilterOptions = [
  { value: "high", label: "High (90%+)", min: 0.9, max: 1.0 },
  { value: "medium", label: "Medium (70-89%)", min: 0.7, max: 0.89 },
  { value: "low", label: "Low (<70%)", min: 0.0, max: 0.69 },
];
